#include <Timer.h>
#include "app_profile.h"
#include "printf.h"
#include "UserButton.h"

module EasyCollectionC {
  uses interface Boot;
  uses interface SplitControl as RadioControl;
  uses interface StdControl as RoutingControl;
  uses interface Send;
  uses interface Leds;
  uses interface Timer<TMilli>;
  uses interface RootControl;
  uses interface Receive;
  //uses interface Packet as RadioPacket;
  
  //serial forwarding
  uses interface SplitControl as SerialControl;
  uses interface AMSend;
  uses interface Packet as SerialPacket;
   
  uses interface Read<uint16_t> as ReadTemp; 
  uses interface Read<uint16_t> as ReadHumi;
  uses interface Read<uint16_t> as ReadLight; 
  uses interface Notify<button_state_t> as UserButton;
}

implementation {
  message_t packet;
  message_t sf_pkt;
  message_t radio_pkt;
  sf_msg* sf_payload;
  radio_msg* Radio_payload;
  bool sendBusy = FALSE;
  bool locked = FALSE;
  //bool FirstReceived[20];
  uint8_t Node_id;
  //uint16_t data[4];//radio sending
  uint16_t Data[4];//serial forwarding
  uint16_t tempdata=0;
  uint16_t humidata=0;
  uint16_t lightdata=0;
  uint16_t co2data=0xffff;
  //uint16_t Nsend=1;
  //uint16_t Nrcv[20];
  //uint16_t Ncheck[20];
  //uint8_t i;

 task void SerialSendTask();
 task void sendMessageTask();
 
  event void Boot.booted() {
    if (TOS_NODE_ID == COORDINATOR_ADDRESS)
{   
    call UserButton.enable();
}

   else {
    call RadioControl.start();
        }
    /*for (i=0;i<20;i++)
   {  
       Nrcv[i]=1;
       Ncheck[i]=0;
       FirstReceived[i]=FALSE;
   }*/
  }

 event void UserButton.notify( button_state_t state ) {
    if ( state == BUTTON_PRESSED ) {
    } else if ( state == BUTTON_RELEASED ) {
      call RadioControl.start();
    }
  }
  
  event void RadioControl.startDone(error_t err) {
    if (err != SUCCESS)
      call RadioControl.start();
    else {
      call RoutingControl.start();
      if (TOS_NODE_ID == COORDINATOR_ADDRESS) 
	{
        call RootControl.setRoot();
        call SerialControl.start(); 
        sf_payload = (sf_msg*)call SerialPacket.getPayload(&sf_pkt, sizeof(sf_msg));
        sf_payload->SrcType = 1; // 1:mote  2:PLC
        }
      else{
	call Timer.startPeriodic(30000);
        //call SerialControl.start();
}
    }
  }

  event void RadioControl.stopDone(error_t err) {}

  task void sendMessageTask() {
    radio_msg* msg =
      (radio_msg*)call Send.getPayload(&packet, sizeof(radio_msg));
    msg->Node_ID = TOS_NODE_ID;
    msg->data1 = tempdata;
    msg->data2 = humidata;
    msg->data3 = lightdata; 
    msg->data4 = co2data;
    //msg->Npkt_send = Nsend;
   
   
if (call Send.send(&packet, sizeof(radio_msg)) != SUCCESS) 
     {call Leds.led0On();
     }
    else 
      {
       call Leds.led1Off();
       call Leds.led2Toggle();
       sendBusy = TRUE;
      }	
  }

  event void Timer.fired() {
    if (!sendBusy){
      call ReadTemp.read();
      call ReadHumi.read();
      call ReadLight.read();
      post sendMessageTask();
    }
  }
 
   event void ReadHumi.readDone(error_t result, uint16_t data)
  {
    if(result == SUCCESS){
      humidata = data;
    }
  }

  event void ReadTemp.readDone(error_t result, uint16_t data)
  {
    if(result == SUCCESS){
      tempdata = data;
    }
  }

    event void ReadLight.readDone(error_t result, uint16_t data)
  {
    if(result == SUCCESS){
      lightdata = data;
    }
  }

 
  event void Send.sendDone(message_t* m, error_t err) {
    if (err != SUCCESS) 
      {call Leds.led0On();
 }  
    else{
    //Nsend=Nsend+1; 
    sendBusy = FALSE;
    }
  }
  
  event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len) {
       call Leds.led1Toggle(); 
     if (TOS_NODE_ID == COORDINATOR_ADDRESS) 
	{
        //Radio_payload = (radio_msg*)call RadioPacket.getPayload(&radio_pkt, sizeof(radio_msg));
        if (len == sizeof(radio_msg)) {
        radio_msg* Radio_payload =(radio_msg*) payload;
        atomic {
                Node_id=Radio_payload->Node_ID;
                Data[0]=Radio_payload->data1;
                Data[1]=Radio_payload->data2;
                Data[2]=Radio_payload->data3;
                Data[3]=Radio_payload->data4;
                //Ncheck[Node_id]=Radio_payload->Npkt_send;
               }
        }

        /*if (Ncheck[Node_id]==1) 
                {Nrcv[Node_id]=1;}
        if (Ncheck[Node_id]<Nrcv[Node_id])
                {Nrcv[Node_id]=Ncheck[Node_id];}
        if (!FirstReceived[Node_id])
                {
                Nrcv[Node_id]=Ncheck[Node_id];
                FirstReceived[Node_id] = TRUE; 
                }
*/
        sf_payload->Node_ID = Node_id;
        sf_payload->data1 = Data[0];
        sf_payload->data2 = Data[1];
        sf_payload->data3 = Data[2];
        sf_payload->data4 = Data[3];
       /* sf_payload->Npkt_rcv = Nrcv[Node_id];
        sf_payload->Npkt_send = Ncheck[Node_id];
        sf_payload->Npkt_loss = Ncheck[Node_id]-Nrcv[Node_id];
        Nrcv[Node_id]=Nrcv[Node_id]+1;*/
        post SerialSendTask();
        }  
    return msg;
  }



task void SerialSendTask()
        {   
  if(locked){
      return;
     }else{
       if(sf_payload == NULL) {return;}
       if(call SerialPacket.maxPayloadLength() < sizeof(sf_msg)){
       return;
	}
      if(call AMSend.send(AM_BROADCAST_ADDR, &sf_pkt, sizeof(sf_msg)) == SUCCESS){
	locked = TRUE;
      }
    }
   }
 
event void AMSend.sendDone(message_t* bufPtr, error_t error){
    if(&sf_pkt == bufPtr){
      locked = FALSE;
    }
  }

  event void SerialControl.startDone(error_t err){}

  event void SerialControl.stopDone(error_t err){}

}
